#pragma once

#include "LeGraphics.h"

#include <QObject>
#include <QVector>

class LEGRAPHICSVIEW_EXPORT LeGraphicsRuler : public QObject
{
    Q_PROPERTY(qreal minimumValueStep READ minimumValueStep WRITE setMinimumValueStep)
    Q_PROPERTY(int minimumTickSpacing READ minimumTickSpacing WRITE setMinimumTickSpacing)
    Q_PROPERTY(int coarseMultiplier READ coarseMultiplier WRITE setCoarseMultiplier)
    Q_PROPERTY(qreal minimumValue READ minimumValue WRITE setMinimumValue)
    Q_PROPERTY(qreal maximumValue READ maximumValue WRITE setMaximumValue)
    Q_PROPERTY(int size READ size WRITE setSize)

    Q_OBJECT
public:
    explicit LeGraphicsRuler(QObject *parent = 0);

    qreal minimumValueStep() const;
    qreal minimumValue() const;
    qreal maximumValue() const;

    qreal ceilValue(qreal value) const;
    qreal floorValue(qreal value) const;
    qreal roundValue(qreal value) const;

    QVector<qreal> majorValues() const;
    qreal majorValueStep() const;
    QVector<qreal> minorValues() const;
    qreal minorValueStep() const;

    int minimumTickSpacing() const;
    int coarseMultiplier() const;
    int size() const;

    QVector<int> majorTicks() const;
    QVector<int> minorTicks() const;

    int tickPosition(qreal value) const;

signals:
    void changed() const;

public slots:
    void setMinimumValueStep(qreal minimumValueStep);
    void setMinimumValue(qreal minimumValue);
    void setMaximumValue(qreal maximumValue);

    void setMinimumTickSpacing(int minimumTickSpacing);
    void setCoarseMultiplier(int coarseMultiplier);
    void setSize(int size);

private:
    qreal m_minimumValueStep;
    int m_minimumTickSpacing;
    int m_coarseMultiplier;
    qreal m_minimumValue;
    qreal m_maximumValue;
    int m_size;

    void invalidate() const;
    void maybeUpdate() const;
    static qreal normaliseValueStep(qreal step);
    int calculateTickPosition(qreal value) const;
    void updateValueSeries(QVector<qreal> &valueSeries, qreal step) const;
    void updateTickSeries(QVector<int> &tickSeries, const QVector<qreal> &valueSeries) const;

    mutable bool m_needsUpdate;
    mutable qreal m_levelOfDetail;
    mutable qreal m_minorValueStep;
    mutable qreal m_majorValueStep;
    mutable QVector<qreal> m_minorValues;
    mutable QVector<qreal> m_majorValues;
    mutable QVector<int> m_minorTicks;
    mutable QVector<int> m_majorTicks;
};
